/*
*  Copyright 2019-2023 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.recitation.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import lombok.RequiredArgsConstructor;
import me.zhengjie.poemmanager.domain.vo.QueryCriteria;
import me.zhengjie.poemmanager.mapper.CommentMapper;
import me.zhengjie.poemmanager.mapper.FavoritesMapper;
import me.zhengjie.poemmanager.mapper.ObjectLikeMapper;
import me.zhengjie.poemmanager.util.ExtractUtil;
import me.zhengjie.recitation.domain.Recitation;
import me.zhengjie.recitation.domain.vo.RecitationQueryCriteria;
import me.zhengjie.recitation.mapper.RecitationMapper;
import me.zhengjie.recitation.service.RecitationService;
import me.zhengjie.recitation.util.FileDeleteUtils;
import me.zhengjie.recitation.util.FileMeta;
import me.zhengjie.recitation.util.FileUpdateUtils;
import me.zhengjie.recitation.util.FileUploadUtils;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageResult;
import me.zhengjie.utils.PageUtil;
import net.dreamlu.mica.core.exception.ServiceException;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
* @description 服务实现
* @author yellow
* @date 2024-12-06
**/
@Service
@RequiredArgsConstructor
public class RecitationServiceImpl extends ServiceImpl<RecitationMapper, Recitation> implements RecitationService {

    private final RecitationMapper recitationMapper;
    private final ObjectLikeMapper objectLikeMapper;
    private final CommentMapper commentMapper;
    private final FavoritesMapper favoritesMapper;
    private final FileUploadUtils fileUploadUtils;
    private final FileDeleteUtils fileDeleteUtils;
    private final FileUpdateUtils fileUpdateUtils;

    @Value("${remote.host}")
    private String host;

    @Value("${remote.port:22}")
    private int port;

    @Value("${remote.username}")
    private String username;

    @Value("${remote.password}")
    private String password;

    @Value("${remote.base-path}")
    private String basePath;

    @Autowired
    private GenericObjectPool<ChannelSftp> sftpPool; // SFTP 连接池

    @Override
    public PageResult<Recitation> findAll(RecitationQueryCriteria criteria, Page<Object> page){
        // 获取基础分页数据
        IPage<Recitation> recitationIPage =recitationMapper.findAll(criteria, page);
        return PageUtil.toPage(recitationIPage);
    }

    @Override
    public PageResult<Recitation>  queryAll(RecitationQueryCriteria criteria, Page<Object> page){
        return PageUtil.toPage(recitationMapper.findAll(criteria,page));

    }
    @Override
    public List<Recitation> queryAll(RecitationQueryCriteria criteria){
        return recitationMapper.findAll(criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileMeta upload(Recitation resources, MultipartFile file) {
        try {
            FileMeta fileMeta = fileUploadUtils.upload(file, resources.getAuthorId(), resources.getPoemId());
            resources.setUrl(fileMeta.getAccessUrl());
            resources.setFilePath(fileMeta.getRemotePath());
            save(resources);
            return fileMeta;
        } catch (Exception e) {
            // 记录详细错误日志（包含上下文信息）
            log.error("朗诵录音上传失败");
            // 抛出明确的业务异常（由全局异常处理器处理）
            throw new ServiceException("朗诵录音上传失败，请检查文件后重试。错误原因: " + e.getMessage());
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileMeta update(Recitation resources, MultipartFile file) {
        Recitation recitation = recitationMapper.getById(resources.getRecitationId());
        // sftp
        //fileUpdateUtils.update(recitation.getFilePath(),file);
        //R2
       return fileUploadUtils.overwriteToR2(file,recitation.getFilePath());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<String> ids)
    {
        removeBatchByIds(ids);
    }

    @Override
    @Transactional(rollbackFor =  Exception.class)
    public void delete(Integer recitationId)
    {
        Recitation r=recitationMapper.getById(recitationId);
        recitationMapper.deleteByRecitationId(recitationId);
        fileDeleteUtils.deleteFromR2(r.getFilePath());
   // sftp     fileDeleteUtils.deleteFile(r.getFilePath(),r.getAuthorId());
    }

    @Override
    public List<Recitation> getMyFavoriteRecitation(String userName) {
        return recitationMapper.getMyFavoriteRecitation(userName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileMeta uploadR2(Recitation resources, MultipartFile file) {
        try {
            // 调用 FileUploadUtils 的 R2 上传实现
            FileMeta fileMeta = fileUploadUtils.uploadToR2(file, resources.getAuthorId(), resources.getPoemId());
            resources.setUrl(fileMeta.getAccessUrl());
            resources.setFilePath(fileMeta.getRemotePath());
            save(resources); // 保存到数据库
            return fileMeta;
        } catch (Exception e) {
            log.error("朗诵录音上传失败", e);
            throw new ServiceException("朗诵录音上传失败，请检查文件后重试。错误原因: " + e.getMessage());
        }
    }

    @Override
    public void download(List<Recitation> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Recitation recitation : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put(" title",  recitation.getTitle());
            map.put(" recitationId", recitation.getRecitationId());
            map.put(" poemId",  recitation.getPoemId());
            map.put(" authorId",  recitation.getAuthorId());
            map.put(" authorName",  recitation.getAuthorId());
            map.put(" url",  recitation.getUrl());
            map.put(" content",  recitation.getContent());
            map.put(" createdAt",  recitation.getCreatedAt());
            map.put(" updatedAt",  recitation.getUpdatedAt());
            map.put(" filePath",  recitation.getFilePath());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<Recitation> getRecitationByUserName(String userName) {
        List<Recitation>recitations=recitationMapper.getRecitationByUserName(userName);
        for (Recitation recitation:
                recitations) {
            String content= ExtractUtil.extrac(recitation.getContent()).replaceAll("\\s*|\r|\n|\t","");
            if(content.length()>50)
                content=content.substring(0,50);
            recitation.setContent(content);
        }
        return recitations;

    }

    @Override
    public Recitation getRecitationById(Integer recitationId) {
        Recitation r=recitationMapper.getById(recitationId);
        r.setComments(commentMapper.getRecitationCommentByObjectId(recitationId));
//        for (Comment c:r.getComments()
//        ) {
//            c.setCountLike(commentMapper.getCountLike(c.getCommentId()));
//        }
        return r;
    }

    @Override
    public ResponseEntity<Object> playRecitationById(Integer recitationId) {
        String remoteFilePath = recitationMapper.getFilePathByRecitationId(recitationId);
        if (Objects.isNull(remoteFilePath)) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
        ChannelSftp channel = null ;
        try {
            channel = sftpPool.borrowObject();
            // 从池中获取 SFTP 连接
            InputStream inputStream = channel.get(remoteFilePath);
            InputStreamResource resource = new InputStreamResource(inputStream); //
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        } catch (JSchException | SftpException e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 归还连接
            if (channel != null) {
                try { sftpPool.returnObject(channel); } catch (Exception ignored) {}
            }
        }
    }

    @Override
    public List<QueryCriteria> queryByTitle(String title) {
        return recitationMapper.queryByTitle(title);
    }

    @Override
    public List<Recitation> getAll() {
        List<Recitation>recitations=recitationMapper.getAll();
        for (Recitation recitation:
                recitations) {
            String content= ExtractUtil.extrac(recitation.getContent()).replaceAll("\\s*|\r|\n|\t","");
            if(content.length()>50)
                content=content.substring(0,50);
            recitation.setContent(content);
        }
        return recitations;
    }
}